package com.vichat.common.util;

import com.vichat.common.vo.http.HttpResponse;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;


/**
 * HTTP工具箱
 */
public final class HttpUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    private final static int bufSize = 8192;

    public static HttpResponse post(String url, String params) {
        return service(url, params, Method.POST, "application/x-www-form-urlencoded");
    }

    public static HttpResponse get(String url) {
        return service(url, null, Method.GET, "application/x-www-form-urlencoded");
    }

    public static HttpResponse json(String url, String params) {
        return service(url, params, Method.POST, "application/json");
    }

    public static HttpResponse post(String url, String params, String contentType) {
        return service(url, params, Method.POST, contentType);
    }

    public static HttpResponse get(String url, String contentType) {
        return service(url, null, Method.GET, contentType);
    }

    private static HttpResponse service(String url, String params, Method method, String contentType) {
        int code = 0;
        String result;
        try {

            URL uri = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
            conn.setRequestMethod(method.toString().toUpperCase());
            conn.setConnectTimeout(500);

            conn.setDoInput(true);
            conn.setDoOutput(true);

            conn.setRequestProperty("Content-Type", contentType);
            conn.setRequestProperty("Accpet-Charset", "UTF-8");

            if (params != null) {
                conn.setRequestProperty("Content-Length", String.valueOf(params.length()));
                PrintWriter writer = new PrintWriter(conn.getOutputStream());
                writer.write(params);
                writer.flush();
            } else {

            }

            StringBuffer buffer = new StringBuffer("");
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            code = conn.getResponseCode();
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            result = buffer.toString();
        } catch (IOException e) {
            result = e.getMessage();
        }
        return new HttpResponse(code, result);
    }

    /**
     * HTTP下载
     */
    public static boolean download(String httpUrl, String saveFile) {

        FileOutputStream fs = null;
        try {
            fs = new FileOutputStream(saveFile);

            URL url = new URL(httpUrl);
            URLConnection conn = url.openConnection();
            InputStream inStream = conn.getInputStream();

            byte[] buffer = new byte[1204];
            int read;
            while ((read = inStream.read(buffer)) != -1) {
                fs.write(buffer, 0, read);
            }
            fs.flush();
            return true;
        } catch (MalformedURLException e1) {
            logger.error("无效的URL", e1);
            return false;
        } catch (FileNotFoundException e) {
            logger.error("目标文件不正确", e);
            return false;
        } catch (IOException e) {
            logger.error("IO异常", e);
            return false;
        } finally {
            if (fs != null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    // IGNORE
                }

            }
        }
    }

    public enum Method {
        GET, POST
    }


    /**
     * 执行一个HTTP GET请求，返回请求响应的HTML
     *
     * @param url         请求的URL地址
     * @param queryString 请求的查询参数,可以为null
     * @return 返回请求响应的HTML
     */
    public static String doGet(String url, String queryString) {
        String response = null;
        HttpClient client = new HttpClient();
        HttpMethod method = new GetMethod(url);
        try {
            if (StringUtils.isNotBlank(queryString))
                method.setQueryString(URIUtil.encodeQuery(queryString));
            client.executeMethod(method);
            if (method.getStatusCode() == HttpStatus.SC_OK) {
                response = method.getResponseBodyAsString();
            }
        } catch (URIException e) {
            logger.error("执行HTTP Get请求时，编码查询字符串“" + queryString + "”发生异常！", e);
        } catch (IOException e) {
            logger.error("执行HTTP Get请求" + url + "时，发生异常！", e);
        } finally {
            method.releaseConnection();
        }
        return response;
    }

    /**
     * 执行一个HTTP POST请求，返回请求响应的HTML
     *
     * @param url    请求的URL地址
     * @param params 请求的查询参数,可以为null
     * @return 返回请求响应的HTML
     */
    public static String doPost(String url, Map<String, String> params) {
        String response = null;
        HttpClient client = new HttpClient();
        HttpMethod method = new PostMethod(url);
        //设置Http Post数据
        if (params != null) {
            HttpMethodParams p = new HttpMethodParams();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                p.setParameter(entry.getKey(), entry.getValue());
            }
            method.setParams(p);
        }
        try {
            client.executeMethod(method);
            if (method.getStatusCode() == HttpStatus.SC_OK) {
                response = method.getResponseBodyAsString();
            }
        } catch (IOException e) {
            logger.error("执行HTTP Post请求" + url + "时，发生异常！", e);
        } finally {
            method.releaseConnection();
        }
        return response;
    }

    /**
     * 检测url地址是否有效
     *
     * @param url
     * @return
     */
    public static boolean urlCheck(String url) {
        boolean flag = false;
        if (url == null || url.length() <= 0) {
            return flag;
        }
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            int state = connection.getResponseCode();
            if (state == 200) {
                flag = true;
            }
        } catch (Exception ex) {
            return flag;
        }
        return flag;
    }

    public static Map<String, String> parseRequest(Map<String, String[]> requestParams){
        Map<String, String> params = new HashMap<>();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            params.put(name, valueStr);
        }
        return params;
    }

    public static String parseRequest(HttpServletRequest request) throws Exception {
        BufferedReader bin = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
        CharArrayWriter arrayWriter = new CharArrayWriter();
        char buf[] = new char[bufSize];
        int ret;
        while ((ret = bin.read(buf, 0, bufSize)) != -1) {
            arrayWriter.write(buf, 0, ret);
        }
        return arrayWriter.toString();
    }

}